#!/bin/bash

# 硬件信息获取脚本
# 作者: Assistant
# 日期: $(date +%Y-%m-%d)

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 显示帮助信息
show_help() {
    echo -e "${BLUE}硬件信息获取脚本使用说明:${NC}"
    echo "运行脚本后，根据菜单选项输入相应数字即可获取对应硬件信息。"
    echo ""
}

# 显示菜单
show_menu() {
    echo -e "${BLUE}======= 硬件信息获取工具 =======${NC}"
    echo "1. 获取所有硬件信息"
    echo "2. 获取CPU信息"
    echo "3. 获取内存信息"
    echo "4. 获取磁盘信息"
    echo "5. 获取网络信息"
    echo "6. 获取GPU信息"
    echo "7. 获取序列号"
    echo "0. 退出程序"
    echo -e "${BLUE}================================${NC}"
}

# 获取CPU信息
get_cpu_info() {
    echo -e "${GREEN}=== CPU信息 ===${NC}"
    lscpu | grep -E "^(Architecture|CPU\(s\)|Thread\(s\) per core|Core\(s\) per socket|Socket\(s\)|Model name):" 
    echo ""
}

# 获取内存信息
get_memory_info() {
    echo -e "${GREEN}=== 内存信息 ===${NC}"
    if command -v dmidecode &> /dev/null; then
        # 计算总内存大小
        total_memory=$(dmidecode -t memory | grep "Size: [0-9]" | awk '{sum += $2} END {print sum}')
        echo "内存总量: ${total_memory}GB"
        
        # 计算内存条数量（只计算实际安装的内存条）
        memory_count=$(dmidecode -t memory | grep "Size: [0-9]" | grep -v "Volatile Size" | wc -l)
        echo "内存条数量: ${memory_count}"
        
        # 获取每条内存的详细信息
        echo "内存详情:"
        dmidecode -t memory | grep -v "Volatile Size" | awk '
        BEGIN { 
            count = 0;
            # 打印表头
            printf "%-10s %-8s %-10s %-8s\n", "内存条", "大小", "类型", "速度";
        }
        /Size: [0-9]/ {
            # 只处理实际安装的内存条，跳过"No Module Installed"的记录
            if ($0 ~ /Size: No Module Installed/) next;        
            size = $2 " " $3;
            count++;
            
            # 读取接下来的几行，找到Type和Speed信息
            type = "未知";
            speed = "未知";
            
            for (i = 0; i < 15; i++) {
                if ((getline line) <= 0) break;
                if (line ~ /Type:/ && line !~ /Error Correction Type:/ && line !~ /Type Detail:/) {
                    gsub(/^[ \t]+|[ \t]+$/, "", line);  # 去除前后空格
                    split(line, arr, ": ");
                    if (arr[2] != "Unknown" && arr[2] != "" && arr[2] != "Unknown") {
                        type = arr[2];
                    }
                }
                if (line ~ /Speed:/ && line !~ /Configured Memory Speed:/) {
                    gsub(/^[ \t]+|[ \t]+$/, "", line);  # 去除前后空格
                    split(line, arr, ": ");
                    if (arr[2] != "Unknown" && arr[2] != "" && arr[2] != "Unknown") {
                        speed = arr[2];
                        if (arr[3] != "" && arr[3] != "Unknown") speed = speed " " arr[3];
                    }
                }
            }
            
            # 打印表格行
            printf "%-10s %-10s %-12s %-15s\n", "内存条" count, size, type, speed;
        }'
    else
        echo "  未安装dmidecode工具"
        free -h | sed 's/^/  /'
    fi
    echo ""
}

# 获取磁盘信息
get_disk_info() {
    echo -e "${GREEN}=== 磁盘信息 ===${NC}"
    # 只显示物理硬盘（类型为disk）
    lsblk -o NAME,SIZE,TYPE,MOUNTPOINT | grep "disk" | awk '{print $1, $2}' | sed 's/^/  /'
    echo ""
}

# 获取网络信息
get_network_info() {
    echo -e "${GREEN}=== 网络信息 ===${NC}"
    # 打印表头
    printf "%-14s %-17s %-20s\n" "网卡名称" "速率" "状态"
    
    # 获取硬件网卡信息，包括网卡名称和速率
    # 只处理物理网卡（存在device目录）
    for interface in $(ls /sys/class/net/); do
        # 检查是否为物理网卡
        if [ -d "/sys/class/net/$interface/device" ]; then
            if command -v ethtool &> /dev/null; then
                # 获取网卡速率和连接状态
                speed=$(ethtool $interface 2>/dev/null | grep "Speed:" | awk '{print $2}')
                link_status=$(ethtool $interface 2>/dev/null | grep "Link detected:" | awk '{print $3}')
                
                if [ "$speed" = "Unknown!" ] || [ -z "$speed" ]; then
                    if [ "$link_status" = "no" ]; then
                        printf "%-10s %-15s %-15s\n" "$interface" "N/A" "未连接"
                    else
                        printf "%-10s %-15s %-15s\n" "$interface" "N/A" "未知"
                    fi
                else
                    printf "%-10s %-15s %-15s\n" "$interface" "$speed" "已连接"
                fi
            else
                # 如果没有ethtool，使用基础信息
                printf "%-10s %-15s %-15s\n" "$interface" "N/A" "未知"
            fi
        fi
    done
    echo ""
}

# 获取序列号
get_serial_number() {
    echo -e "${GREEN}=== 序列号 ===${NC}"
    if command -v dmidecode &> /dev/null; then
        dmidecode -s system-serial-number | sed 's/^/  /'
    else
        echo "  未安装dmidecode工具"
    fi
    echo ""
}

# 获取GPU信息
get_gpu_info() {
    echo -e "${GREEN}=== GPU信息 ===${NC}"
    if command -v nvidia-smi &> /dev/null; then
        # 获取GPU数量
        gpu_count=$(nvidia-smi --query-gpu=count --format=csv,noheader,nounits 2>/dev/null | head -n 1)
        
        # 打印表头
        printf "%-10s %-20s %-20s\n" "GPU索引" "GPU名称" "序列号"
        
        # 循环遍历每个GPU，获取对应的名称和序列号
        for ((i=0; i<gpu_count; i++)); do
            name=$(nvidia-smi -i $i -q | grep "Product Name" | cut -d: -f2 | xargs)
            serial=$(nvidia-smi -i $i --query-gpu=serial --format=csv,noheader,nounits)
            printf "%-10s %-20s %-20s\n" "GPU $i" "$name" "$serial"
        done
    elif command -v lspci &> /dev/null; then
        lspci | grep -i vga
    else
        echo "未检测到GPU信息获取工具"
    fi
    echo ""
}

# 获取所有硬件信息
get_all_info() {
    get_cpu_info
    get_memory_info
    get_disk_info
    get_network_info
    get_gpu_info
    get_serial_number
}

# 处理用户选择
process_choice() {
    case $1 in
        1)
            get_all_info
            ;;
        2)
            get_cpu_info
            ;;
        3)
            get_memory_info
            ;;
        4)
            get_disk_info
            ;;
        5)
            get_network_info
            ;;
        6)
            get_gpu_info
            ;;
        7)
            get_serial_number
            ;;
        0)
            echo -e "${GREEN}感谢使用，再见！${NC}"
            exit 0
            ;;
        *)
            echo -e "${RED}无效选项，请重新选择！${NC}"
            ;;
    esac
}

# 主程序逻辑
main() {
    show_menu
    echo -n "请输入您的选择 [0-7]: "
    read choice
    process_choice $choice
}

# 执行主程序
main

